<?php
class error {

    protected $error_display;
    protected $error_log;
    private $filename;

    public function __construct(){
        // Disable php reporting since
        // this class override it.
        error_reporting(0);

        $this->error_display = true;
        $this->error_log = false;
        $this->filename = null;
    }

    public function setDisplay($status) {
        $this->error_display = $status;
        return $this;
    }

    public function setLog ($status) {
        $this->error_log = $status;
        return $this;
    }

    public function setFilename($filename) {
        if(!is_writable(dirname($filename))){
            return false;
        }
        $this->filename = $filename;
        return true;
    }

    public function getFilename(){
        return $this->filename;
    }

    public function write($message) {

        if(!$this->error_log) {
            return false;
        }

        if(!isset($this->filename)){
            return false;
        }

        if($handle = fopen($this->filename, 'a+')){ 
            fwrite($handle, date('Y-m-d G:i:s') . ' - ' . $message . "\n");
            fclose($handle);
            return true;
        }
    }

    public function handleException(Exception $e) {

        if ($this->error_display) {
            if(ob_get_level() > 0){
                ob_end_clean();
            }
            echo get_class($e) . "<br>";
            echo $e->getMessage() . "<br>";
            echo "File: " . $e->getFile() . " on line " . $e->getLine(). "<br>";
            $trace = $e->getTraceAsString();
            $trace = preg_replace("/\n/", '<br>', $trace);
            echo $trace;
        }

        $message = 'PHP ' . $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine() . "\n" . $e->getTraceAsString() . "\n\n";
        $this->write($message);

        exit();
    }

    /*
     * The following error types cannot be handled with a user defined 
     * function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, 
     * E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised 
     * in the file where set_error_handler() is called.
     *
     * Register a function for execution on shutdown to catch fatal 
     * E_ERROR errors and direct them to handleError
     *
     */
    public function handleShutdown() {

        $errfile = "unknown file";
        $errstr  = "shutdown";
        $errno   = E_CORE_ERROR;
        $errline = 0;

        $error = error_get_last();

        if($error !== NULL) {
            $errno   = $error["type"];
            $errfile = $error["file"];
            $errline = $error["line"];
            $errstr  = $error["message"];

            $this->handleError($errno, $errstr, $errfile, $errline);
        }
    }

    public function handleError($errno, $errstr, $errfile, $errline) {

        switch ($errno) {
        case E_NOTICE:
        case E_USER_NOTICE:
            $error = 'Notice';
            break;
        case E_WARNING:
        case E_USER_WARNING:
            $error = 'Warning';
            break;
        case E_ERROR:
        case E_USER_ERROR:
        case E_CORE_ERROR:
            $error = 'Fatal Error';
            break;
        default:
            $error = 'Unknown';
            break;
        }

        if ($this->error_display) {
            if(ob_get_level() > 0){
                ob_end_clean();
            }
            echo '<b>' . $error . '</b>: ' . $errstr . ' in <b>' . $errfile . '</b> on line <b>' . $errline . '</b>';
        }

        $this->write('PHP ' . $error . ':  ' . $errstr . ' in ' . $errfile . ' on line ' . $errline);

        exit();
    }
}
